const create = Symbol();
const parent = Symbol();
const symbol = {
	create,
	parent,
}

/**
 * 作用域
 */
class Scope {
	/**
	 * 构造函数
	 * @param {Scope} 父作用域
	 */
	constructor (parent) {
		if (parent instanceof Scope) {
			this[symbol.parent] = parent;
		}
	}

	/**
	 * 创建变量
	 * @param {String} key 变量名
	 * @param * 变量值
	 * 
	 */
	[create] (key,value) {
		if(typeof key !== "string") {return;}
		return this[key] = value;
	}
}

let proxy = { 
	get (target, key, receiver) {
		if (key === create) {return target[create].bind(target);}
		if (key === parent) {return target[parent];}
		if (typeof key !== "string") {return;}
		if (new Set(Object.keys(target)).has(key)) {
			return target[key];
		} else if (target[parent]) {
			return target[parent][key];
		}
	},
	set (target, key, value, receiver) {
		if(typeof key !== "string") {return;}
		if(new Set(Object.keys(target)).has(key)) {
			target[key] = value;
		} else if(target[parent]) {
			target[parent][key] = value;
		} else {
			target[create](key, value);
		}
		return true;
	},
	has (target, key) {
		return new Set(Object.keys(target)).has(key) || target[parent] && key in target[parent];
	},
	deleteProperty (target, key) {
		if(typeof key !== "string") {return false;}
		if(new Set(Object.keys(target)).has(key)) {
			return delete target[key];
		} else if (target[parent]) {
			return delete target[parent][key];
		} else {
			return false;
		}
	}, 
	ownKeys (target) {
		let ret;
		if(target[parent]) {
			ret = new Set(Object.getOwnPropertyNames(target[parent]));
			Object.keys(target).map(x => ret.add(x));
		} else {
			ret = new Set(Object.keys(target));
		}
		return [...ret];
	},
	defineProperty (target, propKey, propDesc) {
		return false;
	},
	preventExtensions(target) {
		return false;
	},
	setPrototypeOf(target, proto) {
		return false;
	},
}
/**
 * 创建作用域
 * @param {Scope} parent 父作用域
 * @return {Scope} 创建的作用域
 */
let scope = function scope(parent) {
	return new Proxy(new Scope(parent), proxy);
}
scope.symbol = symbol;
scope.create = create;
scope.is = s => s instanceof Scope;
export default scope;
